﻿/**********************************************************************************
 * Project Name :   
 * Remarks      :  
 * Class Name   :  AssertInstance 
 * Version      :  v1.0.0.0 
 * Author       :  Joey Liang 
 * Description  : 
 * Created Time :  2013/10/16 21:43:04
 * Update Man   :  Joey Liang
 * Update Time  :  2013/10/16 21:43:04
************************************************************************/

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections;
using System.Collections.Generic;

namespace IdleTest.MSTest
{
    public class AssertInstance : IAssertInstance
    {
        #region IAssertInstance成员

        public virtual void AreEqual<T>(T expected, T actual, bool areEqual = true, Func<T, T, bool> compareFunc = null, string message = null)
        {
            if (compareFunc != null)
            {
                bool result = areEqual == compareFunc(expected, actual);
                Assert.IsTrue(result, message);
                return;
            }

            if (!(actual is string) && !(expected is string))
            {
                if (expected is ICollection && actual is ICollection)
                {
                    AreEqual(expected as ICollection, actual as ICollection, null, areEqual, message);
                }
                else if (actual is IEnumerable && expected is IEnumerable && actual != null)
                {
                    Assert.IsTrue(areEqual == TestCommon.CollectionEqual(expected, actual), message);
                }
            }
            
            if (areEqual)
            {
                Assert.AreEqual<T>(expected, actual, message);
            }
            else
            {
                Assert.AreNotEqual<T>(expected, actual, message);
            }
        }

        public virtual void AreEqual(ICollection expected, ICollection actual, IComparer comparer, bool areEqual = true, string message = null)
        {
            if (comparer != null)
            {
                if (areEqual)
                {
                    CollectionAssert.AreEqual(expected, actual, comparer, message);
                }
                else
                {
                    CollectionAssert.AreNotEqual(expected, actual, comparer, message);
                }
            }
            else
            {
                if (areEqual)
                {
                    CollectionAssert.AreEqual(expected, actual, message);
                }
                else
                {
                    CollectionAssert.AreNotEqual(expected, actual, message);
                }
            }
        }

        public virtual void IsNull<T>(T actual, bool assertNull = true, string message = null)
        {
            if (assertNull)
            {
                Assert.IsNull(actual, message);
            }
            else
            {
                Assert.IsNotNull(actual, message);
            }
        }

        public virtual void IsEmpty<T>(T actual, bool isEmpty = true, string message = null)
        {
            if (actual is string)
            {
                Assert.IsTrue(isEmpty == string.IsNullOrEmpty(actual as string), message);
            }
            else if (actual is ICollection)
            {
                ICollection collection = actual as ICollection;
                Assert.IsTrue(isEmpty == (collection == null || collection.Count < 1), message);
            }
            else if (actual is ICollection<T>)
            {
                ICollection<T> collection = actual as ICollection<T>;
                Assert.IsTrue(isEmpty == (collection == null || collection.Count < 1), message);
            }
            else if (!(actual is ValueType))
            {
                IsNull<T>(actual, isEmpty, message);
            }
            else
            {
                Fail("类型不支持断言Empty");
            }
        }

        public virtual void IsInstance(Type expectedType, object actual, bool isInstance = true, string message = null)
        {
            if (isInstance)
            {
                Assert.IsNotNull(actual, message);
                Assert.IsInstanceOfType(actual, expectedType, message);
            }
            else
            {
                Assert.IsNotInstanceOfType(actual, expectedType, message);
            }
        }

        public virtual void Fail(string message = null)
        {
            Assert.Fail(message);
        }

        public virtual void IsBoolean(bool actual, bool isTrue = true, string message = null)
        {
            if (isTrue)
            {
                Assert.IsTrue(actual, message);
            }
            else
            {
                Assert.IsFalse(actual, message);
            }
        }

        public virtual void ThrowException(Action action, bool hasThrow = true, string message = null)
        {
            Exception exception = null;
            try
            {
                action();
            }
            catch (Exception ex)
            {
                exception = ex;
            }

            IsNull(exception, !hasThrow, message);
        }

        public virtual void ThrowException<T>(Action action, bool hasThrow = true, string message = null) 
            where T : Exception
        {
            T exception = null;
            try
            {
                action();
            }
            catch (T ex)
            {
                exception = ex;
            }
            catch { }

            IsNull(exception, !hasThrow, message);
        }

        #endregion
    }
}
